package com.itlong.cloud.propertyapp.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.DTO.app.property.app.PropertyAppDeviceGroupInfoDTO;
import com.itlong.cloud.POJO.DTO.app.property.app.PropertyAppDeviceInfoDTO;
import com.itlong.cloud.POJO.DTO.app.property.app.PropertyAppFeedbackInfoDTO;
import com.itlong.cloud.POJO.DTO.property.PropertySubscriberHanlerDTO;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.app.AppGetQrcodeVO;
import com.itlong.cloud.POJO.VO.app.property.AppGetHouseholdCheckVO;
import com.itlong.cloud.POJO.VO.app.property.app.PropertyAppFeedbackInfoVO;
import com.itlong.cloud.POJO.VO.app.property.app.PropertyAppLoginErrorCacheVO;
import com.itlong.cloud.POJO.VO.app.property.app.PropertyAppUserProjectInfoVO;
import com.itlong.cloud.POJO.VO.common.QrcodeUserInfoVO;
import com.itlong.cloud.POJO.VO.property.PropertyUserCacheVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.app.dao.IAppUserLykzAccountDao;
import com.itlong.cloud.app.service.IAppLykzCloudIntercomAccountService;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.AppQrcodeProtocolVersionEnum;
import com.itlong.cloud.enumerate.DataStatusEnum;
import com.itlong.cloud.enumerate.SystemTypeEnum;
import com.itlong.cloud.enumerate.ecode.PropertyAppErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.PropertyErrorCodeEnum;
import com.itlong.cloud.propertyapp.dao.IPropertyAppUserDao;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.propertyapp.service.IPropertyAppUserInfoService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.encrypt.DesEncryptUtil;
import com.itlong.cloud.utils.encrypt.Md5EncryptUtil;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * <desc>
 *      物业app用户信息业务实现类
 * </desc>
 *
 * @createDate2019/12/25
 **/
@Service
@RefreshScope
public class PropertyAppUserInfoServiceImpl implements IPropertyAppUserInfoService {

    private Logger logger = LoggerFactory.getLogger(PropertyAppUserInfoServiceImpl.class);

    @Value("${"+ PlatformConstants.PROPERTY_APP_USER_TOKEN_KEY +"}")
    private String PROPERTY_APP_USER_TOKEN_KEY;

    @Autowired
    RedisService<PropertyUserCacheVO> redisService;

    @Autowired
    IPropertyAppUserDao iPropertyAppUserDao;

    String userIdSeparator = "_";

    @Autowired
    IAppLykzCloudIntercomAccountService iAppLykzCloudIntercomAccountService;

    @Value("${" + PlatformConstants.LYKZ_APPID + "}")
    String LYKZ_APPID;

    @Autowired
    private MessageSender messageSender;

    @Autowired
    private IAppUserLykzAccountDao iAppUserLykzAccountDao;

    @Autowired
    private RedisService<PropertyAppLoginErrorCacheVO> loginErrorCacheVORedisService;

    String dateFormatStr = "yyyy-MM-dd HH:mm:ss";

    /**
     * <desc>
     *      从缓存中读取用户信息
     * </desc>
     *
     * @param token
     * @return
     * @Author Zhu.yj
     * @createDate  2019/12/25
     */
    @Override
    public PropertyUserCacheVO retrieve(String token) {
        try{
            if (token == null){
                return null;
            }
            String userId = UserTokenUtil.newAPPTokenDecrypt(token,PROPERTY_APP_USER_TOKEN_KEY);
            if (userId == null){
                return null;
            }
            PropertyUserCacheVO propertyUserCacheVO = redisService.getObject(RedisConstant.PROPERTY_APP_REDIS_USER_KEY+userId,PropertyUserCacheVO.class);
            if (propertyUserCacheVO != null && propertyUserCacheVO.getToken().equals(token)){
                String desToken = UserTokenUtil.newAPPTokenDecrypt(propertyUserCacheVO.getToken(),PROPERTY_APP_USER_TOKEN_KEY);
                if (StringUtils.isNotEmpty(desToken) && userId.equals(desToken.split(URLEncoder.encode(userIdSeparator, "UTF-8"))[0])) {
                    //获取当前缓存用户的实时状态
                    propertyUserCacheVO.setStatus(iPropertyAppUserDao.getUserStatus(userId));
                    // 查询项目下是否有未读消息
                    Integer count = iPropertyAppUserDao.getAllUnreadPushInfoCount(propertyUserCacheVO.getProjectId(), userId);
                    propertyUserCacheVO.setHasNewMsg(count > 0 ? "1" : "0");
                    redisService.set(RedisConstant.PROPERTY_APP_REDIS_USER_KEY+userId, RedisConstant.PROPERTY_APP_LOGIN_TIME, propertyUserCacheVO);
                    return propertyUserCacheVO;
                }
            }
            return null;
        } catch (Exception e){
            throw new DataAccessException("【物业app用户信息业务实现类retrieve】从缓存获取用户信息失败",e);
        }
    }

    /**
     * <desc>
     *      获取住户审核列表
     * </desc>
     *
     * @param projectId 项目编号
     * @return List<AppGetHouseholdCheckVO> 住户审核信息集
     * @Author Juguang.S
     * @createDate  2019/12/30
     */
    @Override
    public List<AppGetHouseholdCheckVO> getHoldAuditList(String projectId) {
        return iPropertyAppUserDao.getHoldAuditList(projectId);
    }

    /**
     * <desc>
     *      住户审核通过
     * </desc>
     *
     * @param projectId 项目编号
     * @param auditId   审核通过信息ID
     * @param type    1审核通过 2审核拒绝
     * @return
     * @Author Juguang.S
     * @createDate  2019/12/30
     */
    @Override
    public Integer agreeHoldAudit(String projectId, String auditId,String type) {
        String modifyStatus = "";
        if(type.equals("1")){
            modifyStatus = "2";
        }else{
            modifyStatus = "4";
        }
        return iPropertyAppUserDao.agreeHoldAudit(projectId,auditId,modifyStatus);
    }

    /**
     * <desc>
     *      用户登录验证
     * </desc>
     *
     * @param param
     * @return
     * @Author Zhu.yj
     * @createDate  2019/12/30
     */
    @Override
    public PropertyUserInfoPO getPropertyUserInfo(Map<String, Object> param) throws Exception{
        PropertyUserInfoPO userInfoPO = iPropertyAppUserDao.getPropertyUserInfo(param);
        //如果用户存在，并且administrator_phone不为空 且此用户未向灵云注册或者未在sip中心注册的，则需处理物业用户未注册sip账号及未向灵云注册等问题
        if(userInfoPO != null && StringUtils.isNotEmpty(userInfoPO.getAdministratorPhone())&&StringUtils.isNotEmpty(userInfoPO.getCurrentProjectId())
                && (StringUtils.isEmpty(userInfoPO.getCloudIntercomAccountId()) || StringUtils.isEmpty(userInfoPO.getSipAccount()))){
            this.savePropertyUserSipInfo(userInfoPO,userInfoPO.getCurrentProjectId(),1);
        }
        return userInfoPO;
    }

    /**
     * <desc>
     *      处理物业用户未注册sip账号及未向灵云注册等问题
     * </desc>
     *
     * @param type 1为物业APP登录时调用 type 2为物业平台绑定手机号时调用
     * @Author Juguang.S
     * @createDate  2020/01/08
     */
    public void savePropertyUserSipInfo (PropertyUserInfoPO userInfoPO,String projectId,Integer type) throws Exception{
        String sipAccount = "";
        String lykzId = "";
        String sipPsd = Md5EncryptUtil.md5(userInfoPO.getUserId() + userInfoPO.getAdministratorPhone()).toLowerCase();
        Map<String, Object> params = new HashMap<>();
        Map<String,String> resultMap = iAppLykzCloudIntercomAccountService.getLykzCloudIntercomAccountByMoblie(userInfoPO.getAdministratorPhone(),"");
        if(resultMap==null){
            CloudIntercomAccountInfoPO infoPO = iAppLykzCloudIntercomAccountService.createLykzCloudIntercomAccount(userInfoPO.getUserId(),userInfoPO.getAdministratorPhone(),"","");
            if(infoPO!=null){
                sipAccount = infoPO.getClientUserId();
            }
        }else {
            sipAccount = resultMap.get("lykzUserId");
            //首先根据手机号查询cloud_intercom_account_info表中是否已有该用户灵云信息数据 没有则保存
            if(iAppLykzCloudIntercomAccountService.getExistLykzInfo(resultMap.get("lykzUserId"))==0) {
                CloudIntercomAccountInfoPO infoPO = new CloudIntercomAccountInfoPO();
                lykzId = LogicIdUtil.bussinessId();
                infoPO.setCloudIntercomAccountId(lykzId);
                infoPO.setAccountType(1);
                infoPO.setAccount(resultMap.get("clientNumber"));
                infoPO.setToken(resultMap.get("loginToken"));
                infoPO.setClientPwd(resultMap.get("clientPwd"));
                infoPO.setClientUserId(resultMap.get("lykzUserId"));
                infoPO.setStatus(1);
                infoPO.setCreateTime(new Date());
                infoPO.setAppid(LYKZ_APPID);
                iAppUserLykzAccountDao.save(SqlUtil.durableData(infoPO, PlatformConstants.TABLE_SAVE));
            }else{
                lykzId = iAppUserLykzAccountDao.getCloudIntercomAccountId(resultMap.get("lykzUserId"));
            }
            params.put("userId",userInfoPO.getUserId());
            if(type == 1){
                if(StringUtils.isEmpty(userInfoPO.getCloudIntercomAccountId())){
                    params.put("lykzId",lykzId);
                }
                if(StringUtils.isEmpty(userInfoPO.getSipAccount())){
                    params.put("sipAccount",sipAccount);
                    params.put("sipPsd",sipPsd);
                    this.cloudSipHandler(projectId,sipAccount, sipPsd, null);
                }
            }
            if(type == 2){
                params.put("lykzId",lykzId);
                params.put("sipAccount",sipAccount);
                params.put("sipPsd",sipPsd);
                this.cloudSipHandler(projectId,sipAccount, sipPsd, null);
            }
            iAppUserLykzAccountDao.updatePropertyUserInfo(params);
        }
    }

    /**
     * <desc>
     *      初始化 物业项目人员类型表中的基础数据 只调取一次
     * </desc>
     *
     * @author Jugaung.S
     * @createDate 2021/04/12
     */
    public void modifyPropertyUserTypeData(){
        //查询所有项目编号
        List<String> list = iPropertyAppUserDao.getAllProjectId();
        Date date = new Date();
        List<PropertyProjectUserTypeInfoPO> userTypeInfoPOList = new ArrayList<>();
        for(String projectId : list){
            PropertyProjectUserTypeInfoPO userTypeInfoPO1 = new PropertyProjectUserTypeInfoPO();
            userTypeInfoPO1.setProjectId(projectId);
            userTypeInfoPO1.setUserTypeId(LogicIdUtil.bussinessId());
            userTypeInfoPO1.setSpecialType(1);
            userTypeInfoPO1.setIsDelete(0);
            userTypeInfoPO1.setUserTypeName("户主");
            userTypeInfoPO1.setCreateTime(date);
            userTypeInfoPO1.setUpdateTime(date);
            userTypeInfoPOList.add(userTypeInfoPO1);

            PropertyProjectUserTypeInfoPO userTypeInfoPO2 = new PropertyProjectUserTypeInfoPO();
            userTypeInfoPO2.setProjectId(projectId);
            userTypeInfoPO2.setUserTypeId(LogicIdUtil.bussinessId());
            userTypeInfoPO2.setSpecialType(2);
            userTypeInfoPO2.setIsDelete(1);
            userTypeInfoPO2.setUserTypeName("家属");
            userTypeInfoPO2.setCreateTime(date);
            userTypeInfoPO2.setUpdateTime(date);
            userTypeInfoPOList.add(userTypeInfoPO2);

            PropertyProjectUserTypeInfoPO userTypeInfoPO3 = new PropertyProjectUserTypeInfoPO();
            userTypeInfoPO3.setProjectId(projectId);
            userTypeInfoPO3.setUserTypeId(LogicIdUtil.bussinessId());
            userTypeInfoPO3.setSpecialType(3);
            userTypeInfoPO3.setIsDelete(1);
            userTypeInfoPO3.setUserTypeName("租客");
            userTypeInfoPO3.setCreateTime(date);
            userTypeInfoPO3.setUpdateTime(date);
            userTypeInfoPOList.add(userTypeInfoPO3);
        }
        iPropertyAppUserDao.batchSaveByPropertyUserType(userTypeInfoPOList);
    }

    /**
     * <desc>
     *      对sip数据源中的Sip账号进行添加，更新，或删除操作
     * <desc/>
     * @param  addOrUpdateUserName  根据userName添加或更新Sip数据源的数据（存在则更新，不存在则添加）
     * @param  addOrUpdatePassword  添加或更新Sip数据源的password
     * @param  delUserName  根据userName删除Sip数据源的数据
     * @author Biao.R
     * @createDate 2018/1/9
     */
    public void cloudSipHandler(String projectId,String addOrUpdateUserName, String addOrUpdatePassword, String delUserName) throws Exception {
        PropertySubscriberHanlerDTO subscriberHanlerDTO = new PropertySubscriberHanlerDTO(projectId,addOrUpdateUserName, addOrUpdatePassword, delUserName);
        JSONObject js = new JSONObject();
        js.put("data",JSONObject.toJSON(subscriberHanlerDTO));
        messageSender.send(RabbitMQConstant.RABBITMQ_SAVE_OR_UPDATE_SIP_QUEUE, JsonUtil.toJSON(js), RabbitMQConstant.RABBITMQ_EQUIP_EXCHANGE,
                RabbitMQConstant.RABBITMQ_SAVE_OR_UPDATE_SIP_KEY);
    }

    /**
     * <desc>
     *      获取登录用户的项目列表
     * </desc>
     *
     * @param userId 用户id
     * @return
     * @Author Zhu.yj
     * @createDate  2019/12/31
     */
    @Override
    public List<PropertyAppUserProjectInfoVO> getProjectListByUserId(String userId) throws Exception{
        return iPropertyAppUserDao.getProjectListByUserId(userId);
    }

    /**
     * <desc>
     *      更改物业用户密码
     * </desc>
     *
     * @param params 用户名，密码
     * @return
     * @Author Zhu.yj
     * @createDate  2019/12/31
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public Integer updatePropertyUserPassword(Map<String, Object> params) throws Exception {
        return iPropertyAppUserDao.updatePropertyUserPassword(params);
    }

    /**
     * <desc>
     *      获取物业用户二维码
     * </desc>
     *
     * @param projectId 项目编号
     * @param userId 用户编号
     * @return AppGetQrcodeVO 返回app实体类
     * @Author Juguang.S
     * @createDate  2020/01/03
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public AppGetQrcodeVO getPropertyAppUserQRcode(String projectId,String userId) throws Exception {
        //开始拼接二维码
        StringBuilder heard = new StringBuilder("ITL:{L:");
        StringBuilder content = new StringBuilder();
        //协议版本 1Byte, Hex码
        content.append("V:" + AppQrcodeProtocolVersionEnum.NEW.getType() + ",");
        //查询用户类型
        QrcodeUserInfoVO qrcodeUserInfo = iPropertyAppUserDao.getPropertyUserUid(userId, projectId);
        //用户uid
        if (StringUtils.isNotBlank(qrcodeUserInfo.getUid())) {
            content.append("U:" + qrcodeUserInfo.getUid() + ",");
        } else {
            String uid;
            if ( StringUtils.isNotEmpty(qrcodeUserInfo.getLastUidByPropertyApp()) && !qrcodeUserInfo.getLastUidByPropertyApp().equals("0")) {
                uid = String.format("%s%s","A",StringHandlerUtil.autlSupply(7, (Integer.parseInt(qrcodeUserInfo.getLastUidByPropertyApp().substring(1,qrcodeUserInfo.getLastUidByPropertyApp().length())) + 1) + "", "0"));
//                uid = StringHandlerUtil.autlSupply(8,(qrcodeUserInfo.getLastUidByPropertyApp()+1)+"","0");
                content.append("U:" + uid + ",");
            } else {
                uid = String.format("%s%s","A",StringHandlerUtil.autlSupply(7, "1", "0"));
//                uid = StringHandlerUtil.autlSupply(8,"1","0");
                content.append("U:" + uid + ",");
            }
            //保存uid
            iPropertyAppUserDao.updateUid(userId, projectId, uid);
        }
        //“M”表示用户类型标识符，用户类型固定1Byte，16进制表示。目前具体有以下类型：0x31授权二维码，0x32管理员用户，0x33表示业主或普通用户，0x34表示访客；0x35表示VIP用户、0x36表示残障用户；
        content.append("M:32,");
        //房间编号
        content.append("H:00,");
        //批次号批次或流水号：“B:xxxx”其中“B”表示标识，批次值占用2个字节，用16进制表示0x0000—0xFFFF。
        content.append("I:0001,");
        String startTime = DateUtil.fomatDate(new Date(), DateUtil.YYMMDDHHMM);
        //启用时间
        content.append("T:" + startTime + ",");
        //有效时间 hex 码
        content.append("P:0078,");
        String validCount;
        //有效次数 hex码
        content.append("S:0288,");
        validCount = "0288";
        if (validCount.length() > 2) {
            validCount = validCount.substring(2, 4);
        }
        String value = startTime + "0288" + validCount;
        content.append("G:{N3:0},Q:{N3:0,X3:0,Y:0},");
        //获取项目秘钥
        String projectKey = iPropertyAppUserDao.getQrcodeProjectKey(projectId);
//        logger.info("物业app获取物业用户二维码，项目id：" + projectId + "项目秘钥：" + projectKey);
        String mac = "K:" + DesEncryptUtil.newOwnerAndVisitorMacEncrypt(value, projectKey, content.toString());
//        logger.info("物业app获取物业用户二维码，加密后的K：" + mac);
        String qrcode = heard.toString() + StringHandlerUtil.autlSupply(4, Integer.toHexString((content + mac).length()).toUpperCase(), "0") + "," + content + mac + "}";
//        logger.info("物业app获取物业用户二维码，二维码内容：" + qrcode);
        //保存用户二维码
        iPropertyAppUserDao.updatePropertyRoleProject(userId, projectId, qrcode.toString(), DateUtil.fomatDate1(DateUtil.addCurrentTime(7)),"");
        AppGetQrcodeVO appGetQrcodeVO = new AppGetQrcodeVO();
        appGetQrcodeVO.setQrcode(qrcode.toString());
        appGetQrcodeVO.setEndTime(String.valueOf(DateUtil.addCurrentTime(7).getTime()));
        return appGetQrcodeVO;
    }


    /**
     * <desc>
     *      物业APP用户上传设备排序
     * <desc/>
     *
     * @param propertyAppDeviceInfoDTO 设备排序相关数据
     * @return
     * @author Juguang.S
     * @createDate 2020-01-09
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public Integer upLoadAllSort(PropertyAppDeviceInfoDTO propertyAppDeviceInfoDTO) throws Exception {
        String userId = propertyAppDeviceInfoDTO.getUserId();
        String projectId = propertyAppDeviceInfoDTO.getProjectId();
        String deviceUniques = propertyAppDeviceInfoDTO.getDeviceUniques();
        List<Map<String,Object>> batchParams = new ArrayList<>();
        List<Map<String,Object>> batchUpdateParams = new ArrayList<>();
        iPropertyAppUserDao.updatePropertyRoleProject(userId, projectId, "", "",deviceUniques);
        //保存用户分组信息
        for(PropertyAppDeviceGroupInfoDTO infoDTO : propertyAppDeviceInfoDTO.getGroupAry()){
            PropertyAppDeviceGroupInfoPO infoPO = new PropertyAppDeviceGroupInfoPO();
            infoPO.setGroupId(infoDTO.getGroupId());
            infoPO.setGroupOrder(infoDTO.getDeviceUniques());
            infoPO.setUserId(propertyAppDeviceInfoDTO.getUserId());
            infoPO.setProjectId(propertyAppDeviceInfoDTO.getProjectId());
            infoPO.setGroupName(infoDTO.getGroupName());
            if(iPropertyAppUserDao.isExistByGroupId(infoDTO.getGroupId()) != null){
                infoPO.setUpdateTime(new Date());
                batchUpdateParams.add(SqlUtil.durableData(infoPO, PlatformConstants.TABLE_UPDATE));
            }else{
                infoPO.setCreateTime(new Date());
                batchParams.add(SqlUtil.durableData(infoPO, PlatformConstants.TABLE_SAVE));
            }
        }
        if(!batchParams.isEmpty()){
            iPropertyAppUserDao.batchSave(batchParams);
        }
        if(!batchUpdateParams.isEmpty()){
            iPropertyAppUserDao.batchUpdate(batchUpdateParams);
        }
        //清除获取设备列表缓存
        redisService.del(RedisConstant.REDIS_PROPERTY_APP_USER_DEVICE_CACHE + userId + projectId);
        return 1;
    }

    /**
     * <desc>
     *      退出登录
     * </desc>
     *
     * @param userId 用户id
     * @return
     * @Author Zhu.yj
     * @createDate  2020/1/9
     */
    @Override
    public boolean loginOut(String userId) throws Exception {
        //将缓存时间设置为5s
        PropertyUserCacheVO propertyUserCacheVO =  redisService.getObject(RedisConstant.PROPERTY_APP_REDIS_USER_KEY+userId,PropertyUserCacheVO.class);
        boolean flag = redisService.set(RedisConstant.PROPERTY_APP_REDIS_USER_KEY+userId,RedisConstant.LOGIN_OUT_APP_USER_TOKEN_TIME,propertyUserCacheVO);
        return flag;
    }

    /**
     * <desc>
     *      物业APP用户上传组设备排序
     * <desc/>
     *
     * @param propertyAppDeviceInfoDTO 组设备排序相关数据
     * @return
     * @author Juguang.S
     * @createDate 2020-01-09
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public Integer deviceGroupSort(PropertyAppDeviceInfoDTO propertyAppDeviceInfoDTO) throws Exception {
        String userId = propertyAppDeviceInfoDTO.getUserId();
        String projectId = propertyAppDeviceInfoDTO.getProjectId();
        PropertyAppDeviceGroupInfoPO infoPO = new PropertyAppDeviceGroupInfoPO();
        infoPO.setGroupId(propertyAppDeviceInfoDTO.getGroupId());
        if(StringUtils.isNotEmpty(propertyAppDeviceInfoDTO.getName())){
            infoPO.setGroupName(propertyAppDeviceInfoDTO.getName());
        }
        if(StringUtils.isNotEmpty(propertyAppDeviceInfoDTO.getDeviceUniques())){
            infoPO.setGroupOrder(propertyAppDeviceInfoDTO.getDeviceUniques());
        }
        //组内增减设备，则需property_role_project中device_order进行加或减处理
        if(propertyAppDeviceInfoDTO.getMark().equals("2")){
            String deviceOrder = iPropertyAppUserDao.getPropertyAppUserDeviceOrder(propertyAppDeviceInfoDTO.getUserId(),propertyAppDeviceInfoDTO.getProjectId());
            //处理组内减设备，则需将所减设备拼接至property_role_project中device_order设备排序后
            if(propertyAppDeviceInfoDTO.getType().equals("1")){
                for(String moveStr : propertyAppDeviceInfoDTO.getChangeDevice().split(",")){
                    deviceOrder = StringUtils.remove(deviceOrder,moveStr).replace(",,",",");
                }
            }else if(propertyAppDeviceInfoDTO.getType().equals("2")){
                for(String moveStr : propertyAppDeviceInfoDTO.getChangeDevice().split(",")){
                    deviceOrder = String.format("%s%s%s",deviceOrder,",",moveStr);
                }
                if(StringUtils.isEmpty(propertyAppDeviceInfoDTO.getDeviceUniques())){
                    infoPO.setStatus(DataStatusEnum.DELETE.getType());
                }
            }
            iPropertyAppUserDao.updatePropertyRoleProject(propertyAppDeviceInfoDTO.getUserId(), propertyAppDeviceInfoDTO.getProjectId(), "", "",deviceOrder);
        }

        //由处理相关删除分组逻辑：修改组status状态，及将组内设备拼接至property_role_project中device_order中
        if(propertyAppDeviceInfoDTO.getMark().equals("1")){
            infoPO.setStatus(DataStatusEnum.DELETE.getType());
            String deviceOrder = iPropertyAppUserDao.getPropertyAppUserDeviceOrder(propertyAppDeviceInfoDTO.getUserId(),propertyAppDeviceInfoDTO.getProjectId());
            String groupDeviceOrder = iPropertyAppUserDao.getPropertyAppUserGroupDeviceOrder(propertyAppDeviceInfoDTO.getGroupId());
            deviceOrder = String.format("%s%s%s",deviceOrder,",",groupDeviceOrder);
            iPropertyAppUserDao.updatePropertyRoleProject(propertyAppDeviceInfoDTO.getUserId(), propertyAppDeviceInfoDTO.getProjectId(), "", "",deviceOrder);
        }
        infoPO.setUpdateTime(new Date());
        //清除获取设备列表缓存
        redisService.del(RedisConstant.REDIS_PROPERTY_APP_USER_DEVICE_CACHE + userId + projectId);
        return iPropertyAppUserDao.update(SqlUtil.durableData(infoPO,PlatformConstants.TABLE_UPDATE));
    }

    /**
     * <desc>
     *      更改头像或别名
     * </desc>
     *
     * @param params 更新参数 包含userId,photoUrl或nickName
     * @return
     * @Author Zhu.yj
     * @createDate  2020/1/10
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public Integer updatePhoto(Map<String, Object> params) throws Exception {
        return iPropertyAppUserDao.updatePhotoOrName(params);
    }

    /**
     * <desc>
     *      登陆成功缓存用户信息
     * </desc>
     *
     * @param propertyUserInfoPO 物业用户信息PO
     * @return
     * @Author Zhu.yj
     * @createDate  2020/1/14
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public Map<String, Object> loginCacheUser(PropertyUserInfoPO propertyUserInfoPO,String loginDevice) throws Exception{
        PropertyUserCacheVO propertyUserCacheVO = new PropertyUserCacheVO();
        //设置登录设备
        propertyUserCacheVO.setLoginDevice(loginDevice);
        //设置项目
        PropertyAppUserProjectInfoVO currentProjectInfo = null;
        //先根据项目id 查找相关信息
        List<PropertyAppUserProjectInfoVO> projectMapList = iPropertyAppUserDao.getProjectListByUserId(propertyUserInfoPO.getUserId());
        for (PropertyAppUserProjectInfoVO propertyAppUserProjectInfoVO : projectMapList){
            if ("2".equals(propertyAppUserProjectInfoVO.getStatus())){
                projectMapList.remove(propertyAppUserProjectInfoVO);
            }else if (propertyAppUserProjectInfoVO.getProjectId().equals(propertyUserInfoPO.getCurrentProjectId())){
                currentProjectInfo = propertyAppUserProjectInfoVO;
            }
        }
        //获取用户是否是管理员标记
        List<PropertyRolePO> propertyRolePOS = iPropertyAppUserDao.getPubTypeByRole(StringHandlerUtil.splitString(propertyUserInfoPO.getRoleId()));
        if (propertyRolePOS.get(0).getPubType() == 1){
            propertyUserCacheVO.setCardLevel(1);
        }else {
            propertyUserCacheVO.setCardLevel(0);
        }
        //如果用户信息中存储的项目id 不为空，仍然以此项目id登录
        if (currentProjectInfo != null){
            propertyUserCacheVO.setPubKey(currentProjectInfo.getPubKey());
            propertyUserCacheVO.setProjectId(currentProjectInfo.getProjectId());
            propertyUserCacheVO.setProjectName(currentProjectInfo.getProjectName());
            propertyUserCacheVO.setWatchLimit(currentProjectInfo.getWatchLimit());
            propertyUserCacheVO.setTalkLimit(currentProjectInfo.getTalkLimit());
        }else if (projectMapList.size() != 0){
            propertyUserCacheVO.setPubKey(projectMapList.get(0).getPubKey());
            propertyUserCacheVO.setProjectId(projectMapList.get(0).getProjectId());
            propertyUserCacheVO.setProjectName(projectMapList.get(0).getProjectName());
            propertyUserCacheVO.setWatchLimit(projectMapList.get(0).getWatchLimit());
            propertyUserCacheVO.setTalkLimit(projectMapList.get(0).getTalkLimit());
            //将此项目id存储到用户信息表中
            Map<String, Object> params = new HashMap<>();
            params.put("userId",propertyUserInfoPO.getUserId());
            params.put("projectId",propertyUserCacheVO.getProjectId());
            iPropertyAppUserDao.updateCurrentProjectId(params);
        }
        //设置token
        String token = UserTokenUtil.tokenEncrypt(propertyUserInfoPO.getUserId(),PROPERTY_APP_USER_TOKEN_KEY, SystemTypeEnum.PROPERTY_APP.getType());
        propertyUserCacheVO.setToken(token);
        propertyUserCacheVO.setRoleId(propertyUserInfoPO.getRoleId());
        propertyUserCacheVO.setPhoneNum(propertyUserInfoPO.getAdministratorPhone());
        propertyUserCacheVO.setUserId(propertyUserInfoPO.getUserId());
        propertyUserCacheVO.setUserName(propertyUserInfoPO.getUserName());
        propertyUserCacheVO.setRealName(propertyUserInfoPO.getRealName());
        propertyUserCacheVO.setStatus(propertyUserInfoPO.getStatus());
        propertyUserCacheVO.setPhotoUrl(propertyUserInfoPO.getPhotoUrl());
        propertyUserCacheVO.setLoginDate(DateUtil.fomatDate(new Date()));
        boolean flag = redisService.set(RedisConstant.PROPERTY_APP_REDIS_USER_KEY+propertyUserInfoPO.getUserId(),RedisConstant.PROPERTY_APP_LOGIN_TIME,propertyUserCacheVO);
        if (flag){
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("token",token);
            resultMap.put("projectId",propertyUserCacheVO.getProjectId());
            //登录成功后清除登录错误缓存
            String propertyAppLockCheckKey = String.format("%s%s",RedisConstant.PROPERTY_APP_LOGIN_ERROR_REDIS_KEY,propertyUserInfoPO.getUserId());
            loginErrorCacheVORedisService.del(propertyAppLockCheckKey);
            return resultMap;
        }
        return null;
    }

    /**
     * <desc>
     *      获取用户完整通行记录
     * </desc>
     *
     * @return 分页通行记录
     * @Author Zhu.yj
     * @createDate  2020/1/14
     */
    @Override
    public Map<String, Object> getPassRecordPage(String projectId, String pageIndex, String userId) throws Exception {
        Map<String, Object> params = new HashMap<>();
        Map<String, Object> data = new HashMap<>();
        List<Map<String, Object>> dataAry = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.YMDSQL);
        Calendar calendar = Calendar.getInstance();
        // 今天
        Date today = sdf.parse(sdf.format(calendar.getTime()));
        // 七天前
        calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 7);
        Date weekDay = sdf.parse(sdf.format(calendar.getTime()));
        params.put("projectId", projectId);
        params.put("userId", userId);
        // 分页索引
        if (Integer.parseInt(pageIndex) > 0) {
            params.put("startSlip", (Integer.parseInt(pageIndex) - 1) * 15);
        } else {
            params.put("startSlip", 0);
        }
        // 分页记录数
        params.put("pageSize", 15);
        data.put("pageCount", 0);
        List<Map<String, Object>> recordAry = iPropertyAppUserDao.getPassRecordPage(params);
        // 处理返回数据
        if (recordAry != null && !recordAry.isEmpty()) {
            data.put("pageCount", recordAry.size());
            List<Map<String, Object>> aryToday = new ArrayList<>();
            List<Map<String, Object>> aryWeek = new ArrayList<>();
            List<Map<String, Object>> aryAgo = new ArrayList<>();
            for (Map<String, Object> record : recordAry) {
                if (today.compareTo(sdf.parse(record.get("date").toString())) == 0) {
                    aryToday.add(record);
                } else if (weekDay.compareTo(sdf.parse(record.get("date").toString())) <= 0) {
                    aryWeek.add(record);
                } else {
                    aryAgo.add(record);
                }
            }
            if (!aryToday.isEmpty()) {
                Map<String, Object> mapToday = new HashMap<>();
                mapToday.put("title", "今天");
                mapToday.put("recordAry",aryToday);
                dataAry.add(mapToday);
            }
            if (!aryWeek.isEmpty()) {
                Map<String, Object> mapWeek = new HashMap<>();
                mapWeek.put("title", "一周内");
                mapWeek.put("recordAry",aryWeek);
                dataAry.add(mapWeek);
            }
            if (!aryAgo.isEmpty()) {
                Map<String, Object> mapAgo = new HashMap<>();
                mapAgo.put("title", "更早");
                mapAgo.put("recordAry",aryAgo);
                dataAry.add(mapAgo);
            }
        }
        data.put("dataAry", dataAry);
        return data;
    }

    /**
     * <desc>
     *      保存反馈信息
     * </desc>
     *
     * @param propertyAppFeedbackInfoDTO 物业app反馈信息DTO
     * @return 受影响行数
     * @Author Zhu.yj
     * @createDate  2020/1/15
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public Integer saveFeedback(PropertyAppFeedbackInfoDTO propertyAppFeedbackInfoDTO) throws Exception {
        if (propertyAppFeedbackInfoDTO.getProblemType() == 1){
            //物业app 问题反馈
            propertyAppFeedbackInfoDTO.setProblemType(3);
        }
        if (propertyAppFeedbackInfoDTO.getProblemType() == 2){
            //物业问题反馈
            propertyAppFeedbackInfoDTO.setProblemType(4);
        }
        FeedbackInfoPO feedbackInfoPO = new FeedbackInfoPO();
        BeanUtils.copyProperties(propertyAppFeedbackInfoDTO,feedbackInfoPO);
        feedbackInfoPO.setFeedbackId(LogicIdUtil.bussinessId());
        feedbackInfoPO.setStatus(0);
        feedbackInfoPO.setCreateTime(new Date());
        return iPropertyAppUserDao.save(SqlUtil.durableData(feedbackInfoPO,PlatformConstants.TABLE_SAVE));
    }

    /**
     * <desc>
     *      查询历史反馈信息
     * </desc>
     *
     * @param userId 用户id
     * @param projectId 项目id
     * @param pageNum 页码
     * @return
     * @Author Zhu.yj
     * @createDate  2020/1/15
     */
    @Override
    public Map<String,Object> getHistoryFeedback(String userId, String projectId,String pageNum) throws Exception {
        Map<String, Object> params = new HashMap<>();
        params.put("userId", userId);
        params.put("projectId", projectId);
        params.put("pageSize",15);
        if (Integer.parseInt(pageNum) >0){
            params.put("startSlip",15*(Integer.parseInt(pageNum) - 1));
        }else {
            params.put("startSlip",0);
        }
        List<PropertyAppFeedbackInfoVO> propertyAppFeedbackInfoVOS = iPropertyAppUserDao.getHistoryFeedback(params);
        Map<String, Object> result = new HashMap<>();
        result.put("dataArray",propertyAppFeedbackInfoVOS);
        result.put("pageCount",iPropertyAppUserDao.getHistoryFeedbackCount(params));
        return result;
    }

    /**
     * <desc>
     *      上传常用楼层
     * </desc>
     *
     * @param projectId       项目编号
     * @param deviceUnique    设备序列号
     * @param loadDeviceOrder 常用楼层名称
     * @param userId 用户id
     * @return 1成功，0失败
     * @author Juguang.S
     * @createDate 2020/01/15
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public Integer uploadChoiceFloor(String projectId, String deviceUnique, String loadDeviceOrder, String userId) throws Exception {
        // 查询出权限标识natural_floor
        String naturalFloor = iPropertyAppUserDao.getNaturalFloor(deviceUnique, loadDeviceOrder);
        // 查询用户常用楼层
        String commonFloor = iPropertyAppUserDao.getCommonFloor(userId, projectId);
        Map<String, String> commonFloorMap;
        if (StringUtils.isNotBlank(commonFloor)) {
            commonFloorMap = JSON.parseObject(commonFloor, HashMap.class);
        } else {
            commonFloorMap = new HashMap<>();
        }
        commonFloorMap.put(deviceUnique, naturalFloor);
        commonFloor = JSON.toJSONString(commonFloorMap);
        return iPropertyAppUserDao.updateCommonFloor(userId, projectId, commonFloor);
    }

    /**
     * <desc>
     *      检查当前账号是否被锁定
     * </desc>
     *
     * @param accountNo 登录账号
     * @return
     * @Author Zhu.yj
     * @createDate  2020/2/27
     */
    @Override
    public MessageVO getPropertyAppAccountLockDetail(String accountNo) throws Exception {
        try{
            PropertyUserInfoPO propertyUserInfoPO = iPropertyAppUserDao.getByAccount(accountNo);
            if (propertyUserInfoPO == null || propertyUserInfoPO.getUserId() == null){
                return null;
            }
            String propertyAppLockCheckKey = String.format("%s%s",RedisConstant.PROPERTY_APP_LOGIN_ERROR_REDIS_KEY,propertyUserInfoPO.getUserId());
            PropertyAppLoginErrorCacheVO propertyAppLoginErrorCacheVO = loginErrorCacheVORedisService.getObject(propertyAppLockCheckKey,PropertyAppLoginErrorCacheVO.class);
            Map<String,Object> result = new HashMap<>();
            if (propertyAppLoginErrorCacheVO != null) {

                //计算当前时间和锁定时间，如果小于规定的锁定时间，返回相应提示信息
                String lockTimeStr = propertyAppLoginErrorCacheVO.getLockTime();
                if (StringUtils.isNotEmpty(lockTimeStr)) {
                    Date lockTime = new SimpleDateFormat(dateFormatStr).parse(lockTimeStr);
                    long distanceTime = (new Date().getTime() - lockTime.getTime()) / 1000;
                    long lockLimitTime = PlatformConstants.OPERATE_LOGIN_ERROR_LOCK_TIME;
                    if (distanceTime < lockLimitTime) {
                        //在锁定时间内：返回锁定时间信息
                        result.put("remainTime",((lockLimitTime - distanceTime) / 60) + 1);
                        return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_ERROR_ACCOUNT_LOCKED.getErrorCode(), result);
                    } else {
                        //锁定时间已过，清空该账号的错误缓存数据
                        loginErrorCacheVORedisService.del(propertyAppLockCheckKey);
                    }
                }
            }
            return null;
        }catch (Exception e){
            throw new DataAccessException("【物业app检查账号是否锁定getPropertyAppAccountLockDetail】物业app检查账号是否锁定失败",e);
        }

    }

    /**
     * <desc>
     *      物业app登录错误处理类
     * </desc>
     *
     * @param accountNo 登录账号
     * @return
     * @Author Zhu.yj
     * @createDate  2020/2/27
     */
    @Override
    public MessageVO propertyAppLoginErrorHandler(String accountNo) throws Exception {
        PropertyUserInfoPO propertyUserInfoPO = iPropertyAppUserDao.getByAccount(accountNo);
        if (propertyUserInfoPO == null){
            return new MessageVO(PropertyAppErrorCodeEnum.USER_LOGIN_ERROR.getErrorCode());
        }
        String userId = propertyUserInfoPO.getUserId();

        //最大输入次数
        Integer limitErrorCount = PlatformConstants.OPERATE_LOGIN_MAX_ERROR_COUNT;
        Map<String, Object> result = new HashMap<>();
        String errorCacheKey = String.format("%s%s", RedisConstant.PROPERTY_APP_LOGIN_ERROR_REDIS_KEY, userId);
        PropertyAppLoginErrorCacheVO errorCacheVO = loginErrorCacheVORedisService.getObject(errorCacheKey, PropertyAppLoginErrorCacheVO.class);

        if (errorCacheVO == null) {
            //如果该账号之前没有输入错误，添加登陆错误缓存信息，记录输错次数
            errorCacheVO = new PropertyAppLoginErrorCacheVO(accountNo,userId, 1);
            loginErrorCacheVORedisService.set(errorCacheKey, RedisConstant.OPERATE_LOGIN_ERROR_TIME, errorCacheVO);
            result.put("errorCount", limitErrorCount - 1);
            return new MessageVO(PropertyErrorCodeEnum.PUB_ACCOUNT_PASSWORD_ERR.getErrorCode(), result);
        } else {
            //查询已经错误的次数：如果次数大于5，锁定30分钟
            Integer errorCount = errorCacheVO.getErrorCount();
            if (errorCount + 1 >= limitErrorCount) {
                //生成账号锁定缓存信息
                String lockUserNameKey = String.format("%s%s", RedisConstant.PROPERTY_APP_LOGIN_ERROR_REDIS_KEY, userId);
                errorCacheVO = new PropertyAppLoginErrorCacheVO(accountNo,userId, errorCount);
                errorCacheVO.setLockTime(new SimpleDateFormat(dateFormatStr).format(new Date()));
                loginErrorCacheVORedisService.set(lockUserNameKey, RedisConstant.OPERATE_LOGIN_ERROR_TIME, errorCacheVO);
                result.put("remainTime", PlatformConstants.OPERATE_LOGIN_ERROR_LOCK_TIME / 60);
                return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_ERROR_ACCOUNT_LOCKED.getErrorCode(),result);
            } else {
                //输错次数小于5次，更新缓存信息，并给出相应提示
                errorCacheVO = new PropertyAppLoginErrorCacheVO(accountNo,userId, errorCount + 1);
                loginErrorCacheVORedisService.set(errorCacheKey, RedisConstant.OPERATE_LOGIN_ERROR_TIME, errorCacheVO);
                result.put("errorCount", limitErrorCount - errorCount - 1);
                return new MessageVO(PropertyErrorCodeEnum.PUB_ACCOUNT_PASSWORD_ERR.getErrorCode(), result);
            }
        }
    }

    /**
     * <desc>
     *      查询角色详细信息
     * </desc>
     *
     * @param roleId 角色id,多个逗号隔开
     * @return
     * @Author Zhu.yj
     * @createDate  2020/3/2
     */
    @Override
    public List<PropertyRolePO> getPubTypeByRole(String roleId) throws Exception {
        String[] roleIds = StringHandlerUtil.splitString(roleId);
        return iPropertyAppUserDao.getPubTypeByRole(roleIds);
    }

    /**
     * <desc>
     *      根据userId获取第三方token
     * </desc>
     *
     * @param userId 用户id
     * @return
     * @Author Zhu.yj
     * @createDate  2020/3/2
     */
    @Override
    public String getUserClientToken(String userId) throws Exception {
        return iPropertyAppUserDao.getUserClientToken(userId);
    }

    /**
     * <desc>
     *      物业APP用户设置分组名称
     * <desc/>
     *
     * @param propertyAppDeviceInfoDTO 分组ID
     * @return
     * @author Juguang.S
     * @createDate 2020-01-09
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public Integer setDeGroupName(PropertyAppDeviceInfoDTO propertyAppDeviceInfoDTO) throws Exception {
        String userId = propertyAppDeviceInfoDTO.getUserId();
        String projectId = propertyAppDeviceInfoDTO.getProjectId();
        PropertyAppDeviceGroupInfoPO infoPO = new PropertyAppDeviceGroupInfoPO();
        infoPO.setGroupId(propertyAppDeviceInfoDTO.getGroupId());
        infoPO.setGroupName(propertyAppDeviceInfoDTO.getName());
        infoPO.setUpdateTime(new Date());
        //清除获取设备列表缓存
        redisService.del(RedisConstant.REDIS_PROPERTY_APP_USER_DEVICE_CACHE + userId + projectId);
        return iPropertyAppUserDao.update(SqlUtil.durableData(infoPO,PlatformConstants.TABLE_UPDATE));
    }


    /**
     * <desc>
     *      根据手机号获取物业用户信息
     * </desc>
     *
     * @param phoneNo 手机号
     * @return
     * @Author Zhu.yj
     * @createDate  2020/3/12
     */
    @Override
    public PropertyUserInfoPO getByAccount(String phoneNo) throws Exception {
        return iPropertyAppUserDao.getByAccount(phoneNo);
    }

    /**
     * <desc>
     *      更新用户当前项目id
     * </desc>
     *
     * @param projectId 项目id
     * @param userId 用户id
     * @return
     * @Author Zhu.yj
     * @createDate  2020/3/16
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public Integer updateCurrentProjectId(String projectId, String userId) throws Exception {
        Map<String, Object> params = new HashMap<>();
        params.put("projectId",projectId);
        params.put("userId",userId);
        return iPropertyAppUserDao.updateCurrentProjectId(params);
    }

    /**
     * <desc>
     *      根据deviceUnique查询居住楼层集合使用于物业APP
     * </desc>
     *
     * @param deviceUnique 设备唯一码
     * @return
     * @Author Juguang.S
     * @createDate  2020/04/16
     */
    @Override
    public List<String> getLiveFloorByDeviceUnique(String deviceUnique){
        return iPropertyAppUserDao.getLiveFloorByDeviceUnique(deviceUnique);
    }
}
